use rustcloud_core::{Request, Response, ServiceError, ServiceInstance, ServiceResult, Transport};
use rustcloud_core::http_client::{HttpClientConfig, HttpClientFactory};
use async_trait::async_trait;
use reqwest::{Client, Method, Url};
use std::time::Duration;
use tracing::{debug, warn, error};
use serde::{Deserialize, Serialize};

/// 传输配置（重新导出统一配置）
pub type TransportConfig = HttpClientConfig;

/// HTTP传输层实现
#[derive(Clone)]
pub struct HttpTransport {
    client: Client,
    config: TransportConfig,
}

impl HttpTransport {
    pub fn new() -> Self {
        Self::with_config(HttpClientConfig::for_transport())
    }
    
    pub fn with_config(config: TransportConfig) -> Self {
        let client = HttpClientFactory::create_reqwest_client(&config)
            .expect("Failed to create HTTP client for transport");
            
        Self { client, config }
    }
    
    /// 重试发送请求
    async fn send_with_retry(&self, request: Request, instance: &ServiceInstance) -> ServiceResult<Response> {
        let mut last_error = None;
        let mut last_response = None;
        
        for attempt in 0..=self.config.retry_count {
            if attempt > 0 {
                debug!("Retrying request, attempt {}/{}", attempt, self.config.retry_count);
                tokio::time::sleep(self.config.retry_delay).await;
            }
            
            match self.send_once(&request, instance).await {
                Ok(response) => {
                    if response.is_success() || !self.should_retry(response.status) {
                        return Ok(response);
                    }
                    // For HTTP error codes that we want to retry, save the response
                    last_response = Some(response);
                },
                Err(err) => {
                    if !self.is_retryable_error(&err) {
                        return Err(err);
                    }
                    last_error = Some(err);
                }
            }
        }
        
        // If we have a response (even an error one), return it
        if let Some(response) = last_response {
            return Ok(response);
        }
        
        Err(last_error.unwrap_or_else(|| 
            ServiceError::NetworkError("All retry attempts failed".to_string())
        ))
    }
    
    /// 单次发送请求
    async fn send_once(&self, request: &Request, instance: &ServiceInstance) -> ServiceResult<Response> {
        let url_str = format!("{}://{}:{}{}", instance.scheme, instance.host, instance.port, request.path);
        let url = Url::parse(&url_str).map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        let http_method = match request.method.as_str() {
            "GET" => Method::GET,
            "POST" => Method::POST,
            "PUT" => Method::PUT,
            "DELETE" => Method::DELETE,
            "PATCH" => Method::PATCH,
            "HEAD" => Method::HEAD,
            "OPTIONS" => Method::OPTIONS,
            _ => return Err(ServiceError::NetworkError(format!("Unsupported HTTP method: {}", request.method))),
        };

        let mut req_builder = self.client.request(http_method, url.clone());

        // 添加请求头
        for (key, value) in &request.headers {
            req_builder = req_builder.header(key, value);
        }
        
        // 添加查询参数
        if !request.query_params.is_empty() {
            req_builder = req_builder.query(&request.query_params);
        }

        // 添加请求体
        if let Some(body) = &request.body {
            req_builder = req_builder.body(body.clone());
        }

        debug!("Sending HTTP request to {}", url);
        let http_response = req_builder
            .send()
            .await
            .map_err(|e| {
                error!("HTTP request failed: {}", e);
                ServiceError::NetworkError(e.to_string())
            })?;

        let status = http_response.status().as_u16();
        let headers = http_response
            .headers()
            .iter()
            .map(|(k, v)| (k.to_string(), v.to_str().unwrap_or("").to_string()))
            .collect();
        let body = http_response
            .bytes()
            .await
            .map_err(|e| ServiceError::NetworkError(e.to_string()))?;

        debug!("Received HTTP response with status {}", status);
        Ok(Response {
            status,
            headers,
            body: Some(body.to_vec()),
        })
    }
    
    /// 判断是否应该重试
    fn should_retry(&self, status: u16) -> bool {
        // 对于5xx错误和部分4xx错误进行重试
        match status {
            // 服务器错误，可以重试
            500..=599 => true,
            // 部分客户端错误，可以重试
            408 | 409 | 429 => true,
            // 其他不重试
            _ => false,
        }
    }
    
    /// 判断错误是否可重试
    fn is_retryable_error(&self, error: &ServiceError) -> bool {
        match error {
            ServiceError::NetworkError(_) => true,
            ServiceError::TimeoutError(_) => true,
            _ => false,
        }
    }
}

#[async_trait]
impl Transport for HttpTransport {
    async fn send(&self, request: Request, instance: &ServiceInstance) -> ServiceResult<Response> {
        self.send_with_retry(request, instance).await
    }

    async fn send_batch(
        &self,
        requests: Vec<(Request, &ServiceInstance)>,
    ) -> Vec<ServiceResult<Response>> {
        let futures = requests.into_iter().map(|(request, instance)| {
            self.send(request, instance)
        });
        futures::future::join_all(futures).await
    }

    fn name(&self) -> &str {
        "http"
    }
}

impl Default for HttpTransport {
    fn default() -> Self {
        Self::new()
    }
}